package com.haotian.redis.pool;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.log4j.Logger;

import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import redis.clients.util.Pool;

/**
 * 本类只适用于基于 {@link redis.clients.util.Pool } 开发的类 返回Jedis 实例 请对号入座。
 * 
 * @author 张昊天 2018年1月15日
 */
public class RedisSentinelAndBasicPool {

	private Pool<Jedis> pool = null;

	private RedisSentinelAndBasicPool(Builder b) {
		this.pool = b.pool;
	}

	public static class Builder {

		Logger log = Logger.getLogger(this.getClass());
		JedisPoolConfig config = null;
		Pool<Jedis> pool = null;
		Set<HostAndPort> nodes = null;
		String passWord = null;
		boolean openSentinel = false;
		String sentinelName = null;
		int redisTimeOut = 20000;

		/**
		 * redis IP 地址：端口如果开启哨兵需要给一组 如果不开启 默认取第一个 HostAndPort
		 * 
		 * @param addr
		 * @return
		 */
		public Builder setAddr(Set<HostAndPort> nodes) {
			this.nodes = nodes;
			return this;
		}

		/**
		 * 密码 可为空
		 * 
		 * @param password
		 * @return
		 */
		public Builder setPassWord(String password) {
			this.passWord = password;
			return this;
		}

		/**
		 * 是否开启哨兵 true / false
		 * 
		 * @param openSentine
		 * @return
		 */
		public Builder setOpenSentinel(boolean openSentinel) {
			this.openSentinel = openSentinel;
			return this;
		}

		/**
		 * 哨兵名称 和redis中 配置的哨兵名称必须相同 开启哨兵有效
		 * 
		 * @param sentinelName
		 * @return
		 */
		public Builder setSentinelName(String sentinelName) {
			this.sentinelName = sentinelName;
			return this;
		}

		/**
		 * 超时时间 单位 毫秒
		 * 
		 * @param redisTimeOut
		 * @return
		 */
		public Builder setRedisTimeOut(int redisTimeOut) {
			this.redisTimeOut = redisTimeOut;
			return this;
		}

		public RedisSentinelAndBasicPool build(JedisPoolConfig config) {

			if (nodes == null || nodes.size() < 1) {
				log.error("构建_JedisPool时 Redis地址为空");
				throw new RuntimeException("地址为空");
			}

			if (!openSentinel) {
				log.info("没有开启哨兵,默认获取地址数组第一位。");
			}

			if (openSentinel && sentinelName == null) {
				throw new RuntimeException("哨兵开启的情况下 哨兵名称必须设置");
			}

			// 如果开启哨兵
			if (this.openSentinel) {

				log.info("#哨兵为开启状态#");

				Set<String> sentineAddr = new HashSet<String>();

				for (Iterator<HostAndPort> ite = nodes.iterator(); ite.hasNext();) {
					HostAndPort next = ite.next();
					sentineAddr.add(next.toString());
				}

				log.info("#哨兵地址#：" + Arrays.toString(sentineAddr.toArray()));

				if (this.passWord == null) {
					log.info("#警告!没有设置密码#");
					this.pool = new JedisSentinelPool(sentinelName, sentineAddr, config, redisTimeOut);
				} else {
					this.pool = new JedisSentinelPool(sentinelName, sentineAddr, config, redisTimeOut, this.passWord);
				}
			} else {
				log.info("#哨兵为关闭状态#");

				HostAndPort hostAndPort = nodes.iterator().next();

				log.info("#Redis地址#：" + hostAndPort.toString());
				if (passWord == null) {
					log.info("#警告!没有设置密码#");
					this.pool = new JedisPool(config, hostAndPort.getHost(), hostAndPort.getPort(), this.redisTimeOut);
				} else {
					this.pool = new JedisPool(config, hostAndPort.getHost(), hostAndPort.getPort(), this.redisTimeOut,
							passWord);
				}
			}
			return new RedisSentinelAndBasicPool(this);
		}

	}

	/**
	 * 获取Jedis实例
	 * 
	 * @return
	 */
	public Jedis getJedis() {
		if (null == pool)
			return null;
		return pool.getResource();
	}
}
